package org.yanse.structures.linkedList;

import org.yanse.node.ListNode;

import java.util.NoSuchElementException;

public class LinkedList {
    private ListNode head;

    public LinkedList() {

    }

    public LinkedList(int[] arrays) {
        if (arrays == null || arrays.length == 0) {
            return;
        }
        head = new ListNode(arrays[0]);

        ListNode current = head;
        for (int i = 1; i < arrays.length; i++) {
            current.next = new ListNode(arrays[i]);
            current = current.next;
        }
    }

    public int get(int index) {
        if (head == null) {
            throw new NoSuchElementException();
        }
        ListNode current = head;
        int currentIndex = 0;
        while (current != null) {
            if (currentIndex == index) {
                return current.val;
            }
            currentIndex++;
            current = current.next;
        }
        throw new NoSuchElementException(
                String.format("index subscript element does not exist, index = %d", index));
    }

    public int getFirst() {
        if (head == null) {
            throw new NoSuchElementException();
        }
        return head.val;
    }

    public int getLast() {
        if (head != null) {
            ListNode current = head;
            while (current != null) {
                if (current.next == null) {
                    return current.val;
                }
                current = current.next;
            }
        }
        throw new NoSuchElementException();
    }

    public void printLinkedList() {
        ListNode current = head;
        while (current != null) {
            System.out.print(current.val + " ");
            current = current.next;
        }
    }

    public void add(int ele) {
        addLast(ele);
    }

    public void add(int index, int ele) {
        ListNode eleNode = new ListNode(ele);
        if (head == null) {
            head = eleNode;
            return;
        }

        int currentIndex = 0;
        ListNode current = head;
        ListNode lastNode = null;
        while (current != null) {
            if (currentIndex == index) {
                if (lastNode == null) {
                    eleNode.next = head;
                    head = eleNode;
                } else {
                    lastNode.next = eleNode;
                    eleNode.next = current;
                }
                return;
            }
            lastNode = current;
            current = current.next;
            currentIndex++;
        }

        throw new NoSuchElementException(
                String.format("index subscript element does not exist, index = %d", index));
    }

    public void addFirst(int ele) {
        ListNode firstNode = new ListNode(ele);
        firstNode.next = head;
        head = firstNode;
    }

    public void addLast(int ele) {
        ListNode lastNode = new ListNode(ele);
        if (head == null) {
            head = lastNode;
            return;
        }
        ListNode current = head;
        while (current != null) {
            if (current.next == null) {
                current.next = lastNode;
                break;
            }
            current = current.next;
        }
    }

    public void removeFirst() {
        if (head == null) {
            throw new NoSuchElementException();
        }
        head = head.next;
    }

    public void removeLast() {
        if (head == null) {
            throw new NoSuchElementException();
        }

        ListNode current = head;
        ListNode lastNode = null;
        while (current != null) {
            if (current.next == null) {
                if (lastNode == null) {
                    head = null;
                } else {
                    lastNode.next = null;
                }
                break;
            }
            lastNode = current;
            current = current.next;
        }
    }

    public void set(int index, int ele) {
        if (head == null) {
            throw new NoSuchElementException();
        }
        ListNode current = head;
        int currentIndex = 0;
        while (current != null) {
            if (currentIndex == index) {
                current.val = ele;
                return;
            }
            current = current.next;
            currentIndex++;
        }

        throw new NoSuchElementException(
                String.format("index subscript element does not exist, index = %d", index));
    }

    public void reverse() {
        if (head == null) {
            return;
        }

        ListNode current = head;
        ListNode lastNode = null;
        ListNode nextNode = null;
        while (current != null) {
            nextNode = current.next;
            current.next = lastNode;
            lastNode = current;
            current = nextNode;
        }
        head = lastNode;
    }
}
